## PROJECT SETUP
cmake_minimum_required(VERSION 3.9 FATAL_ERROR)
project(Rat-DistmeshCPP VERSION 2.017.7 LANGUAGES CXX)

# switchboard
option(ENABLE_TESTING "Build unit/system tests" ON)
option(ENABLE_EXAMPLES "Build examples" ON)

# ensure out of core build
if(PROJECT_SOURCE_DIR STREQUAL PROJECT_BINARY_DIR)
  message(FATAL_ERROR "In-source builds not allowed. Please make a new directory (called a build directory) and run CMake from there.\n")
endif()

# set build type
if(NOT CMAKE_BUILD_TYPE)
  set(CMAKE_BUILD_TYPE Release)
endif()

# C++ standard
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)

# compiler options
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
	message(STATUS "using GCC settings")
	set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -g")
	set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -march=native -O3")
elseif (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
	message(STATUS "using Clang settings")
	set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -g")
	set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -march=native -O3")
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
	message(STATUS "using MSVC settings")
	set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /utf-8")
	set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /O2")
else()
	message(STATUS "Compiler not recognized")
endif()

# windows specific
if(WIN32)
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
endif()

# output paths
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/bin CACHE PATH "" FORCE)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/lib CACHE PATH "" FORCE)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/lib CACHE PATH "" FORCE)

# report
message(STATUS "building in ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}")


## EXTERNAL LIBRARIES
# find the rat common library
find_package(RatCommon 2.017.7 REQUIRED)

## LIBRARY
# add the library
add_library(ratdmsh SHARED
	src/distfun.cpp
	src/dfairfoil.cpp
	src/dfcircle.cpp
	src/dfdiff.cpp
	src/dfellipse.cpp
	src/dfintersect.cpp
	src/dfones.cpp
	src/dfpolygon.cpp
	src/dfrectangle.cpp
	src/dfrrectangle.cpp
	src/dfscale.cpp
	src/dfunion.cpp
	src/dfplasma.cpp
	src/dfarray.cpp
	src/dfarrayangular.cpp
	src/dftransform.cpp
	src/distmesh2d.cpp
	src/serializer.cpp
	src/perimeter.cpp
	src/dfmultipole.cpp
)

# Add an alias so that library can be used inside the build tree, e.g. when testing
add_library(Rat::Dmsh ALIAS ratdmsh)

# properties
set_target_properties(ratdmsh PROPERTIES VERSION ${PROJECT_VERSION})
set_target_properties(ratdmsh PROPERTIES SOVERSION 1)

# add include directory
target_include_directories(ratdmsh
	PUBLIC 
		$<INSTALL_INTERFACE:include>    
		$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
		$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/include>
	PRIVATE
		${CMAKE_CURRENT_SOURCE_DIR}/src
)

# enable warnings
target_compile_options(ratdmsh PRIVATE 
	$<$<OR:$<CXX_COMPILER_ID:Clang>,$<CXX_COMPILER_ID:AppleClang>,$<CXX_COMPILER_ID:GNU>>:
		-Wpedantic -Wall -Wextra -Wsuggest-override -Wold-style-cast>
	$<$<CXX_COMPILER_ID:MSVC>:
		/W3>)

# link libraries
target_link_libraries(ratdmsh PUBLIC Rat::Common)

# Version header file
configure_file(
	${CMAKE_CURRENT_SOURCE_DIR}/cmake/version.hh.in 
	${CMAKE_CURRENT_BINARY_DIR}/include/version.hh)

## UNIT/SYSTEM TESTS
# check switchboard
if(ENABLE_TESTING)
	# use cmake's platform for unit testing
	enable_testing()

	# add test directory
	add_subdirectory(test)
endif()

## EXAMPLES
# check switchboard
if(ENABLE_EXAMPLES)
	# add example directory
	add_subdirectory(examples)
endif()

# disable windows warnings
if(WIN32)
	target_compile_definitions(ratdmsh PUBLIC -D_CRT_SECURE_NO_WARNINGS)
endif()

# copy database files to build directory
file(COPY json DESTINATION ${CMAKE_CURRENT_BINARY_DIR})

## INSTALLATION
# get install directories
include(GNUInstallDirs)
set(INSTALL_CONFIGDIR ${CMAKE_INSTALL_LIBDIR}/cmake/ratdmsh)

install(TARGETS ratdmsh
	EXPORT ratdmsh-targets
	LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/rat
	ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}/rat
	RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)

# This is required so that the exported target has the name RatCmn and not ratcmn
set_target_properties(ratdmsh PROPERTIES EXPORT_NAME Dmsh)

install(DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/rat/dmsh)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/include/version.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/rat/dmsh)

# Export the targets to a script
install(EXPORT ratdmsh-targets
	FILE
		RatDmshTargets.cmake
	NAMESPACE
		Rat::
	DESTINATION
		${INSTALL_CONFIGDIR}
)

# Create a ConfigVersion.cmake file
include(CMakePackageConfigHelpers)
write_basic_package_version_file(
	${CMAKE_CURRENT_BINARY_DIR}/RatDmshConfigVersion.cmake
	VERSION ${PROJECT_VERSION}
	COMPATIBILITY AnyNewerVersion
)

configure_package_config_file(${CMAKE_CURRENT_LIST_DIR}/cmake/RatDmshConfig.cmake.in
	${CMAKE_CURRENT_BINARY_DIR}/RatDmshConfig.cmake
	INSTALL_DESTINATION ${INSTALL_CONFIGDIR}
)

# Install the config, configversion and custom find modules
install(FILES
	${CMAKE_CURRENT_BINARY_DIR}/RatDmshConfig.cmake
	${CMAKE_CURRENT_BINARY_DIR}/RatDmshConfigVersion.cmake
	DESTINATION ${INSTALL_CONFIGDIR}
)

## EXPORT
export(EXPORT ratdmsh-targets
	FILE ${CMAKE_CURRENT_BINARY_DIR}/RatDmshTargets.cmake
	NAMESPACE Rat::)

# Register package in user's package registry
export(PACKAGE RatDmsh)

#####################
# Setup install paths
#####################

include(GNUInstallDirs)

# Set RPATHS
SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
list(APPEND CMAKE_INSTALL_RPATH "$ORIGIN/../${CMAKE_INSTALL_LIBDIR}")

# Create Debian package, must be the last thing
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake")
include(GenerateDebianPackage)
